
import { ElMessage } from "element-plus";
/**
 * 地形开挖
 */

class SceneTerrainWa {
  constructor(viewer, options = {}) {
    this._viewer = viewer;
    this.options = options;
    this.handler = new Cesium.ScreenSpaceEventHandler(
      this._viewer.scene.canvas
    );  
    this.points = [];
    this.controls = [];
    this.hierarchy = [];
    this.drawLayer = new Cesium.CustomDataSource("绘制图层");
    this._viewer.dataSources.add(this.drawLayer);
    this.tempDarwLayer = new Cesium.CustomDataSource("临时绘制图层");
    this._viewer.dataSources.add(this.tempDarwLayer);

    this._viewer.scene.globe.depthTestAgainstTerrain = true;

    this.ClipPlanes = [];
    this.minHeight;
  }
  start(waHeight = 100) {
    this.options.height = waHeight;
    ElMessage({
      type: "success",
      message: "左键加点,右击结束绘制！",
      duration: 3000,
      offset: 60
    });
    this.clearWa();
    // //将数组清空
    this.points = [];
    this.hierarchy = [];
    this.controls = [];
    let tempPolygon;
    this.handler.setInputAction((e) => {
      let position = this._viewer.scene.pickPosition(e.position);
      if (Cesium.defined(position)) {
        this.tempDarwLayer.entities.add({
          position: position,
          point: {
            pixelSize: 5,
            color: Cesium.Color.YELLOW,
            outline: true,
            outlineWidth: 2,
            outlineColor: Cesium.Color.AQUA
          }
        });
        this.points.push(position);
      }
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

    this.handler.setInputAction((evt) => {
      if (this.points.length <= 1) return;
      let position = this._viewer.scene.pickPosition(evt.endPosition);
      if (Cesium.defined(position)) {
        let tempPolygonHierarchy = [];
        this.points.forEach((item) => {
          tempPolygonHierarchy.push(item.clone());
        });
        tempPolygonHierarchy[tempPolygonHierarchy.length] = position;
        if (Cesium.defined(tempPolygon)) {
          this.tempDarwLayer.entities.remove(tempPolygon);
        }
        tempPolygon = new Cesium.Entity({
          polygon: {
            hierarchy: new Cesium.CallbackProperty(() => {
              return new Cesium.PolygonHierarchy(tempPolygonHierarchy);
            }, false),
            material: Cesium.Color.YELLOW.withAlpha(0.5),
            outline: true,
            outlineWidth: 5,
            outlineColor: Cesium.Color.AQUA
          }
        });
        this.tempDarwLayer.entities.add(tempPolygon);
      }
    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

    this.handler.setInputAction(() => {
      this.tempDarwLayer.entities.removeAll();
      this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
      this.handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE);

      //判断点位顺序
      let arr = this.points.map((e) => {
        let carto = Cesium.Cartographic.fromCartesian(e);
        carto.longitude = Cesium.Math.toDegrees(carto.longitude);
        carto.latitude = Cesium.Math.toDegrees(carto.latitude);
        return carto;
      });
      let x1 = arr[0].longitude;
      let y1 = arr[0].latitude;
      let x2 = arr[1].longitude;
      let y2 = arr[1].latitude;
      let x3 = arr[2].longitude;
      let y3 = arr[2].latitude;
      let dirRes = (x2 - x1) * (y3 - y2) - (y2 - y1) * (x3 - x2);
      let isR = dirRes > 0;
      let points = [];
      if (isR) {
        for (let li = 0; li < arr.length; li++) {
          points[li] = Cesium.Cartesian3.fromDegrees(
            arr[li].longitude,
            arr[li].latitude,
            arr[li].height
          );
        }
      } else {
        let count = 0;
        for (let li = arr.length - 1; li >= 0; li--) {
          points[count] = Cesium.Cartesian3.fromDegrees(
            arr[li].longitude,
            arr[li].latitude,
            arr[li].height
          );
          count++;
        }
      }
      this.points = points;
      this.controls = this.points;
      this.controls.forEach((e, index) => {
        if (index == this.controls.length - 1) {
          this.interpolation(e, this.controls[0]);
        } else {
          this.interpolation(e, this.controls[index + 1]);
        }
      });
      this.createClipPlane(this.points);

      //绘制面、贴纹理
      this.addPolygon(this.hierarchy);
      this.removeEvent();
    }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
  }

  createClipPlane(points) {
    let length = points.length;

    //计算裁切平面
    for (let i = 0; i < length; i++) {
      let nextIndex = (i + 1) % length;

      //计算两个笛卡尔坐标的按分量求和
      let midPoint = Cesium.Cartesian3.add(
        points[i],
        points[nextIndex],
        new Cesium.Cartesian3()
      );

      //缩放笛卡尔坐标
      midPoint = Cesium.Cartesian3.multiplyByScalar(midPoint, 0.5, midPoint);

      //计算笛卡尔坐标系的标准形式
      let up = Cesium.Cartesian3.normalize(midPoint, new Cesium.Cartesian3());

      //计算两个笛卡尔坐标的分量化差异
      let right = Cesium.Cartesian3.subtract(
        points[nextIndex],
        midPoint,
        new Cesium.Cartesian3()
      );

      //计算笛卡尔坐标的标准化形式
      right = Cesium.Cartesian3.normalize(right, right);

      //计算两个笛卡尔坐标的叉(外)乘积
      let normal = Cesium.Cartesian3.cross(right, up, new Cesium.Cartesian3());

      //计算提供的笛卡尔坐标的标准化形式
      normal = Cesium.Cartesian3.normalize(normal, normal);

      //原始中心平面
      let originCenteredPlane = new Cesium.Plane(normal, 0.0);

      //计算点到平面的有符号的最短距离
      let distance = Cesium.Plane.getPointDistance(
        originCenteredPlane,
        midPoint
      );
      this.ClipPlanes.push(new Cesium.ClippingPlane(normal, distance));
    }

    this.ClippingPlaneCollection = new Cesium.ClippingPlaneCollection({
      planes: this.ClipPlanes,
      edgeWidth: 1.0,
      edgeColor: Cesium.Color.YELLOW
    });

    this._viewer.scene.globe.clippingPlanes = this.ClippingPlaneCollection;
  }

  //封装绘制面、贴纹理函数 // 这是侧面墙面
  addPolygon(hierarchy) {
    this.drawLayer.entities.add({
      polygon: {
        hierarchy: Cesium.Cartesian3.fromDegreesArrayHeights(hierarchy),
        material: new Cesium.ImageMaterialProperty({
          image: this.options.img
        }),
        closeTop: false, // 这个要设置为false
        extrudedHeight: this.minHeight - this.options.height || -100,
        perPositionHeight: true // 这个要设置true
      }
    });
  }
  //获取指定位置高度
  getHeight(position) {
    let height = this._viewer.scene.globe.getHeight(position);
    return height;
  }

  //清空kaiwa
  clearWa() {
    this._viewer.scene.globe.clippingPlanes = null;
    this.points = [];
    this.controls = [];
    this.hierarchy = [];
    this.ClipPlanes = [];
    this.drawLayer.entities.removeAll();
    this.tempDarwLayer.entities.removeAll();
  }

  //样条插值
  interpolation(point1, point2) {
    let spline = new Cesium.LinearSpline({
      times: [0.0, 1],
      points: [point1, point2]
    });

    for (let i = 0; i <= 100; i++) {
      let cartesian3 = spline.evaluate(i / 100);

      let cartographic = Cesium.Cartographic.fromCartesian(cartesian3);

      let lat = Cesium.Math.toDegrees(cartographic.latitude);
      let lng = Cesium.Math.toDegrees(cartographic.longitude);
      let height = this.getHeight(cartographic);

      this.hierarchy.push(lng);
      this.hierarchy.push(lat);
      this.hierarchy.push(height);

      this.minHeight = Math.min(
        this.minHeight ? this.minHeight : height,
        height
      );
    }
  }

  //事件移除
  removeEvent() {
    this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
    this.handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE);
    this.handler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK);
  }
}

export default SceneTerrainWa;
